import coin.proto.account_control_pb2 as control_proto
from coin.support.account_control.approach_target_position_strategy \
  import ApproachTargetPositionStrategy
from coin.support.account_control.rest_account_operation_executor import (
    RestAccountOperationExecutor)


def _check_account_operation_request(control_request: control_proto.ControlRequest):
  assert control_request.HasField('account_operation')
  operation = control_request.account_operation
  assert operation.HasField('operation_type')
  operation_type = operation.operation_type
  if operation_type in (control_proto.QUERY_FILLS, control_proto.QUERY_ORDERS):
    assert control_request.target.HasField('product')


def _check_control_request_proto(control_request: control_proto.ControlRequest):
  assert control_request.HasField('target')
  target = control_request.target
  assert target.HasField('market_type') and \
         target.HasField('exchange') and \
         target.HasField('owner')
  assert control_request.HasField('type')
  control_type = control_request.type
  if control_type == control_proto.CONTROL_ACCOUNT_OPERATION:
    _check_account_operation_request(control_request)


def _process_approach_position_request(control_request: control_proto.ControlRequest):
  strategy = ApproachTargetPositionStrategy(control_request)
  control_response = strategy.start()
  return control_response


def _process_account_operation_request(control_request: control_proto.ControlRequest):
  control_response = RestAccountOperationExecutor.request(control_request)
  return control_response


def dispatch_control_request(control_request: control_proto.ControlRequest):
  _check_control_request_proto(control_request)
  control_type = control_request.type
  control_type_handler_map = {
      control_proto.CONTROL_ACCOUNT_OPERATION: _process_account_operation_request,
      control_proto.CONTROL_APPROACH_POSITION: _process_approach_position_request
  }

  assert control_type in control_type_handler_map, \
    'Fail to dispatch control type: %s' % control_type
  handler = control_type_handler_map[control_type]
  control_response = handler(control_request)
  return control_response
